// Copyright 2008 web2me.dev
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

package net.web2me.cli;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import net.web2me.api.IParser;
import net.web2me.api.ParserException;
import net.web2me.api.ParserFactory;
import net.web2me.api.ProcessFinishedException;
import net.web2me.api.util.CliParams;
import net.web2me.api.util.FileUtil;
import net.web2me.api.util.SiteStreamGenerator;
import net.web2me.api.util.multiurl.MultiUrl;
import net.web2me.api.util.multiurl.MultiUrlUtil;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

/**
 * A CLI client
 * @author web2me
 *
 */
public class Web2MeCli {
	private static Logger logger = Logger.getLogger(Web2MeCli.class);
	private static String url;
	private static String dir;
	private static String parserName;
	private static long totalTimeStart;
	private static long totalTimeStop;

	/**
	 * @param args This method expects 3 arguments: url, destiny directory and parser name
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		if((System.getProperty("debug") != null && Boolean.valueOf(System.getProperty("debug")))){
			PropertyConfigurator.configure(Web2MeCli.class.getResource("/log4j-debug.properties"));
		}
		
		if( checkParameters(args) ){
			totalTimeStart = System.currentTimeMillis();
			
			try {
				logger.info("Processing: " + url);
				
				ParserFactory.setParsersDirectory(new File(getRealPath() + "/parsers"));
				
				IParser parser = ParserFactory.getParser(parserName);
				
				List<MultiUrl> multiUrls = MultiUrlUtil.getMultiUrls(url);

				for(MultiUrl multi: multiUrls){
					parser.setDir(dir + (multi.getMatchedPattern().equals("") ? "": "/" + multi.getMatchedPattern()));
					parser.setUrl(multi.getUrl());
					
					String siteStream = SiteStreamGenerator.getStream(multi.getUrl());
					
					try{
						parser.process( siteStream.toString() );
					}catch (ParserException e){
						throw new Exception(e);
					}catch (ProcessFinishedException e){
						
					}
				}
				
				if(CliParams.isSet("metadata")){
					logger.debug("Saving the metadata");
					
					FileUtil.setContents(new File(dir + "/.web2me.metadata"), 
							"Date: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss (Z)").format(new Date()) + "\n" +
							"Parser: " + parserName + "\n" +
							"URL: " + url + "\n" +
							"Destiny: " + dir + "\n");
				}
				
				if(CliParams.isSet("history")){
					FileUtil.appendContents(new File(getRealPath() + "/.web2me.history"), 
							new SimpleDateFormat("yyyy-MM-dd HH:mm:ss (Z)").format(new Date()) + "\t" +
							parserName + "\t" + url + "\t" + dir + "\n");
				}
				
				totalTimeStop = System.currentTimeMillis();
				
				logger.info("The process has finished");
				
				processFinished();
			} catch (Exception e) {
				logger.error("An error ocurred while executing:");
				logger.error(e);
			}
		}
	}
	
	private static void processFinished() {
		logger.info("Site Downloader status");
		logger.info("**********************");
		logger.info("Total execution time: " + calcuteTime(totalTimeStart, totalTimeStop));
	}

	private static String calcuteTime(long start, long stop){
		long ms = stop - start;
		
		long sec = ms / 1000;
		ms = ms % 1000;
		
		long min = sec / 60;
		sec = sec % 60;
		
		long hours = min / 60;
		min = min % 60;
		
		return hours + " hours, " + min + " minutes and " + sec + " seconds";
	}
	
	/**
	 * Checks that the parameters has been correctly passed to the program.<br>
	 * The supported parameters are:
	 * <ul>
	 * 	<li><b>-u</b> or <b>--url</b>: The URL of the site that is going to be parsed
	 * <li><b>-d</b> or <b>--directory</b>: The directory where the content of the site is going to be downloaded
	 * <li><b>-p</b> or <b>--parser</b>: The parser that id that can handle the site
	 * <li><b>-h</b> or <b>--help</b>: Displays the help menu
	 * </ul>
	 * @param params
	 * @return true if the parameters are ok, or false if they are wrong or the user used <code>-h</code> or <code>--help</code>
	 */
	private static boolean checkParameters(String[] params){
		if(params == null){
			return false;
		}
		
		for( int i = 0; i < params.length; i++){
			if( params[i].equals( "-u" ) || params[i].equals( "--url" ) ){
				url = params[++i];
			}else if( params[i].equals( "-d" ) || params[i].equals( "--directory" ) ){
				dir = params[++i];
			}else if( params[i].equals( "-p" ) || params[i].equals( "--parser" ) ){
				parserName = params[++i];
			}else if( params[i].equals( "-h" ) || params[i].equals( "--help" ) ){
				showHelp();
				return false;
			}else if( params[i].equals( "-l" ) || params[i].equals( "--parsers-list" ) ){
				showParsersList();
				return false;
			}
		}
		
		return true;
	}
	
	private static void showParsersList(){
		List<Properties> properties = null;
		try {
			ParserFactory.setParsersDirectory(new File("parsers"));
			properties = ParserFactory.getParsersPropertyFiles();
			
			System.out.println(" ");
			System.out.println("Media2Me parsers list:");
			System.out.println("----------------------");
			System.out.println(" ");
			
			for(Properties prop: properties){
				System.out.println(prop.getProperty("parser.id") + " \t" + prop.getProperty("parser.description"));
			}
			System.out.println(" ");
		} catch (Exception e) {
			logger.fatal("Error reading parser.properties files", e);
		}
	}
	
	private static void showHelp(){
		System.out.println(" ");
		System.out.println("Media2Me usage: java [VMPARAMETERS] -jar web2me.jar [PARAMETERS]");
		System.out.println("------------------------------------------------------------------");
		System.out.println(" ");
		System.out.println("Example:");
		System.out.println("java -jar web2me.jar -u http://www.fotolog.com/user -d \"/home/user/flogs\" -p UbbiFotolog");
		System.out.println(" ");
		System.out.println("Parameters for helping information:");
		System.out.println("-h\tShows this menu");
		System.out.println("-l\tShows a list of available parsers");
		System.out.println(" ");
		System.out.println("Parameters needed to download content:");
		System.out.println("-------------------------");
		System.out.println("-u\tSite URL (ie. http://www.fotolog.com/user)");
		System.out.println("-d\tDestiny directory (ie. \"/home/user/flog\" or \"c:/My Documents/flogs\" - Don't use backslash)");
		System.out.println("-p\tParser ID (ie. \"ImageFap\" or \"UbbiFotolog\" or \"ClubLez\" etc)");
		System.out.println(" ");
		System.out.println("VM parameters list:");
		System.out.println("-------------------------");
		System.out.println("The VM parameters are optional");
		
		System.out.println("-Dhistory=[true|false]\tDisable/enable the downaload history (default to true)");
		System.out.println("-Dmetadata=[true|false]\tDisable/enable the metadata file on the destiny folder (default to true)");
		System.out.println(" ");
	}
	
	/**
	 * Gets the real physical path where the jar is located 
	 * @return The real path
	 */
	private static String getRealPath(){
		URL currentDir = Web2MeCli.class.getResource("/log4j-debug.properties");
		String fullPath = currentDir.getFile().toString().replace("file:", "");
		// 2 times is ok
		fullPath = fullPath.substring(0, fullPath.lastIndexOf("/"));
		fullPath = fullPath.substring(0, fullPath.lastIndexOf("/"));
		
		return fullPath;
	}
}